package com.guet.DataStructures.sparseArr;

import java.io.*;

/**
 * @author MicahYin
 * @date 2020/10/8 16:45
 * java数据结构——矩阵及稀疏矩阵
 * 1. java实现原始矩阵与稀疏矩阵之间的转换
 * 2. 实现将矩阵保存为本地文件
 */
public class SparseArray {
    public static void main(String[] args) {
        //原始数组
        int chessArray[][] = new int[11][11];
        chessArray[1][2] = 1;
        chessArray[2][3] = 2;
        System.out.println("原始的二维数组~~");
        for (int[] row:chessArray){
            for (int data:row){
                System.out.printf("%d\t",data);
            }
            System.out.println();
        }
        //原始数组-->稀疏数组
        /**
         * 1.先遍历原始数组，计算出原始数组中非0数据的个数sum
         * 2.根据sum创建稀疏数组
         * 3.再次遍历原数组，将原数组的数据存入稀疏数组
         */
        int sum = 0;
        for(int i=0;i<11;i++){
            for(int j=0;j<11;j++){
                if (chessArray[i][j]!=0){
                    sum++;
                }
            }
        }
        //创建稀疏数组
        int sparseArr[][] = new int[sum+1][3];
        sparseArr[0][0] = 11;
        sparseArr[0][1] = 11;
        sparseArr[0][2] = sum;
        int count = 0;
        for(int i=0;i<11;i++){
            for(int j=0;j<11;j++){
                if (chessArray[i][j]!=0){
                    count++;
                    sparseArr[count][0] = i;
                    sparseArr[count][1] = j;
                    sparseArr[count][2] = chessArray[i][j];
                }
            }
        }
        //控制台输出稀疏数组
        System.out.println("稀疏数组~~");
        for (int[] row:sparseArr){
            for (int data:row){
                System.out.printf("%d\t",data);
            }
            System.out.println();
        }
        /**
         * 将稀疏数组保存到文件，随后将其读取打印在控制台
         */
        //将创建的稀疏数组保存到文件
        intDataToFileOut(sparseArr,new File("./data.txt"));

        int[][] sparseArrayFromFile = getSparseArrayFromFile();
        System.out.println("----------------");
        for (int i=0;i<sparseArrayFromFile.length;i++){
            for (int j=0;j<sparseArrayFromFile.length;j++){
                System.out.printf("%d\t",sparseArrayFromFile[i][j]);
            }
            System.out.println("\n");
        }
        System.out.println("----------------");

        /**
         * 稀疏数组--->原始数组
         */
        int chessArr2[][] = new int[sparseArr[0][0]][sparseArr[0][1]];
        System.out.println(sparseArr.length);
        for (int i=1;i<sparseArr.length;i++){
            chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }
        System.out.println("还原数组~~");
        for (int[] row:chessArr2){
            for (int data:row){
                System.out.printf("%d\t",data);
            }
            System.out.println();
        }
    }

    /**
     * 将数组保存为txt文件
     * @param sparseArray
     * @param file
     */
    private static void intDataToFileOut(int[][] sparseArray,File file){
        FileWriter out = null;
        try {
            out = new FileWriter(file);
            for (int i=0;i<sparseArray.length;i++){
                for (int j=0;j<sparseArray.length;j++){
                    //将每个元素转换为字符串
                    String content = String.valueOf(sparseArray[i][j]);
                    out.write(content+"\t");
                }
                out.write("\r\n");
            }
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取数组文件
     * @return
     */
    private static int[][] getSparseArrayFromFile(){
        //将稀疏矩阵从文件中读取出来
        BufferedReader bufferedReader = null;
        //为保存的数组分配空间，此处我们知道保存的稀疏数组为3*3，所以直接定义3*3，如果不知道大小的话
        //可以先通过读一遍文件，将数组的大小确定下来，然后再初始化，随后再次读取文件，但是这样也就读取了两遍文件...
        //目前没有想到更好的办法....
        int[][] datas = new int[3][3];;
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(new File("data.txt")));
            bufferedReader = new BufferedReader(inputStreamReader);
            String line = null;
            int i=0;
            //按行读取
            while((line = bufferedReader.readLine() )!= null){
                if(null != line){
                    //将按行读取的字符串按空格分割，得到一个string数组
                    String[] strings = line.split("\\t");
                    //依次转换为int类型存入到分配好空间的数组中
                    for(int k = 0;k<strings.length;k++){
                        datas[i][k] = Integer.valueOf(strings[k]);
                    }
                    //行数加1
                    i++;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        //返回读取的二维数组
        return datas;
    }
}
